﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HTTPServer
{
    public enum RequestMethod
    {
        GET,
        POST,
        HEAD
    }

    public enum HTTPVersion
    {
        HTTP10,
        HTTP11,
        HTTP09
    }

    class Request
    {
        string[] requestLines;
        RequestMethod method;
        public string relativeURI;
        Dictionary<string, string> headerLines;

        public Dictionary<string, string> HeaderLines
        {
            get { return headerLines; }
        }

        HTTPVersion httpVersion;
        string requestString;
        string[] contentLines;

        public Request(string requestString)
        {
            this.requestString = requestString;


        }
        /// <summary>
        /// Parses the request string and loads the request line, header lines and content, returns false if there is a parsing error
        /// </summary>
        /// <returns>True if parsing succeeds, false otherwise.</returns>
        public bool ParseRequest()
        {

            //TODO: parse the receivedRequest using the \r\n delimeter   

            this.requestLines = requestString.Split(new string[] { "\r\n" }, StringSplitOptions.None);

            // check that there is atleast 3 lines: Request line, Host Header, Blank line (usually 4 lines with the last empty line for empty content)
            if (this.requestLines.Length < 3)
            {
                return false;
            }
            // Parse Request line
            if (!ParseRequestLine())
            {
                return false;
            }
            // Validate blank line exists
            if (!ValidateBlankLine())
            {
                return false;
            }
            // Load header lines into HeaderLines dictionary
            if (!LoadHeaderLines())
            {
                return false;
            }

            return true;
        }

        private bool ParseRequestLine()
        {

            string[] requestLineParts = this.requestLines[0].Split(' ');
            if (requestLineParts.Length < 2)
            {
                return false;
            }
            switch (requestLineParts[0])
            {
                case "GET":
                    this.method = RequestMethod.GET;
                    break;
                case "POST":
                    this.method = RequestMethod.POST;
                    break;
                case "HEAD":
                    this.method = RequestMethod.HEAD;
                    break;
                default:
                    return false;
            }

            if (!ValidateIsURI(requestLineParts[1]))
            {
                return false;
            }

            this.relativeURI = requestLineParts[1];

            if (requestLineParts.Length == 3)
            {
                switch (requestLineParts[2])
                {
                    case "HTTP/1.0":
                        this.httpVersion = HTTPVersion.HTTP10;
                        break;
                    case "HTTP/1.1":
                        this.httpVersion = HTTPVersion.HTTP11;
                        break;
                }
            }
            else
            {
                this.httpVersion = HTTPVersion.HTTP09;
            }
            return true;
        }

        private bool ValidateIsURI(string uri)
        {
            return Uri.IsWellFormedUriString(uri, UriKind.RelativeOrAbsolute);
        }

        private bool LoadHeaderLines()
        {
            if (this.requestLines.Length < 2)
            {
                return false;
            }

            int indexOfBlankLine = this.requestLines.ToList().IndexOf(string.Empty); //Index of returns -1 if not found


            this.headerLines = new Dictionary<string, string>();
            for (int i = 1; i < indexOfBlankLine; i++)
            {
                string[] parts = requestLines[i].Split(':');
                headerLines.Add(parts[0].Trim().ToLower(), parts[1].Trim().ToLower());
            }

            return true;
        }

        private bool ValidateBlankLine()
        {
            int indexOfBlankLine = this.requestLines.ToList().IndexOf(string.Empty); //Index of returns -1 if not found
            if (indexOfBlankLine == -1)
            {
                return false;
            }
            return true;
        }

    }
}
